---
sidebar_label: LDAP
description: This is the API documentation for the OpenBao LDAP secrets engine.
---

# LDAP secrets engine (API)

:::warning

**Note**: This engine can use external X.509 certificates as part of TLS or signature validation.
   Verifying signatures against X.509 certificates that use SHA-1 is deprecated and is no longer
   usable without a workaround. See the
   [deprecation FAQ](/docs/deprecation/faq#q-what-is-the-impact-of-removing-support-for-x-509-certificates-with-signatures-that-use-sha-1)
   for more information.

:::

This is the API documentation for the OpenBao LDAP secrets engine. For general
information about the usage and operation of the LDAP secrets engine,
please see the [LDAP secrets engine docs](/docs/secrets/ldap).

This documentation assumes the LDAP secrets engine is enabled at the `/ldap` path
in OpenBao. Since it is possible to mount secrets engines at any path, please
update your API calls accordingly.

## Configuration management

This endpoint configures the LDAP secret engine to manage user entries.

| Method   | Path               |
| :------- | :----------------- |
| `POST`   | `/ldap/config` |
| `GET`    | `/ldap/config` |
| `DELETE` | `/ldap/config` |

:::info

**Note**: The LDAP entry used by `config` should have the necessary privileges
to search and change entry passwords in LDAP.

:::

### Parameters

- `binddn` `(string: <required>)` - Distinguished name (DN) of object to bind for managing user entries.
  For example, `cn=openbao,ou=Users,dc=openbao,dc=com`.
- `bindpass` `(string: <required>)` - Password to use along with `binddn` for managing user entries.
- `url` `(string: "ldap://127.0.0.1")` - The LDAP server to connect to. Examples: `ldaps://ldap.myorg.com`,
  `ldaps://ldap.myorg.com:636`. This can also be a comma-delineated list of URLs, e.g.
  `ldaps://ldap.myorg.com, ldaps://ldap.myorg.com:636`, in which case the servers will be tried in-order if
  there are errors during the connection process.`.
- `password_policy` `(string: <optional>)` - The name of the [password policy](/docs/concepts/password-policies)
  to use to generate passwords. Note that this accepts the name of the policy, not the policy itself.
- `schema` `(string: "openldap")` - The LDAP schema to use when storing entry passwords.
  Valid schemas include `openldap`, `ad`, and `racf`.
- `userdn` `(string: <optional>)` - The base DN under which to perform user search in
  [library management](/api-docs/secret/ldap#library-management) and [static roles](/api-docs/secret/ldap#static-roles).
  For example, `ou=Users,dc=openbao,dc=com`.
- `userattr` `(string: <optional>)` – The attribute field name used to perform user search
  in [library management](/api-docs/secret/ldap#library-management) and [static roles](/api-docs/secret/ldap#static-roles).
  Defaults to `cn` for the `openldap` schema, `userPrincipalName` for the `ad` schema, and
  `racfid` for the `racf` schema.
- `upndomain` (string: `optional`) - The domain (userPrincipalDomain) used to construct a UPN
  string for authentication. The constructed UPN will appear as `[binddn]@[upndomain]`. For
  example, if `upndomain=example.com` and `binddn=admin`, the UPN string `admin@example.com`
  will be used to log in to Active Directory.
- `connection_timeout` `(integer: 30 or string: "30s")` - Timeout, in seconds, 
  when attempting to connect to the LDAP server before trying the next URL in 
  the configuration.
- `request_timeout` `(integer: 90, string: "90s" <optional>)` - Timeout, in seconds, for the connection when
  making requests against the server before returning back an error.
- `starttls` `(bool: <optional>)` - If true, issues a `StartTLS` command after establishing an unencrypted connection.
- `insecure_tls` `(bool: <optional>)` - If true, skips LDAP server SSL certificate verification - insecure,
  use with caution!
- `certificate` `(string: <optional>)` - CA certificate to use when verifying LDAP server certificate, must be
  x509 PEM encoded.
- `client_tls_cert` `(string: <optional>)` - Client certificate to provide to the LDAP server, must be x509
  PEM encoded.
- `client_tls_key` `(string: <optional>)` - Client key to provide to the LDAP server, must be x509 PEM encoded.

**Deprecated Parameters**:

- `length` `(int: 64)` - The length of generated password strings. Note: some schemas may require shorter
  password lengths (such as `racf`). Mutually exclusive with `password_policy`

**Note about password generation**:

`length` and `password_policy` cannot both be set in the configuration. The `POST` endpoint will reject the
configuration if both are specified.

- If neither are set, this will default to a reasonable default password generation algorithm (the same algorithm as
  prior to the introduction of password policies).
- If `length` is set, the same algorithm is used, but with the length specified instead of the default length.
- If `password_policy` is set, the password will be generated from the associated
  [password policy](/docs/concepts/password-policies). The policy is not exercised prior to saving the configuration.
  The policy will need to exist prior to passwords needing to be generated by this engine, but does not need to exist
  prior to saving the configuration.

See [LDAP secrets engine docs](/docs/secrets/ldap) for additional information.

### Sample payload

```json
{
  "binddn": "cn=openbao,ou=Users,dc=openbao,dc=com",
  "bindpass": "pa$$w0rd",
  "url": "ldaps://127.0.0.11"
}
```

### Sample POST request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/ldap/config
```

### Sample GET request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request GET \
    https://127.0.0.1:8200/v1/ldap/config
```

### Sample response

```json
{
  "data": {
    "binddn": "cn=admin,dc=openbao,dc=com",
    "case_sensitive_names": false,
    "certificate": "",
    "insecure_tls": false,
    "length": 64,
    "schema": "openldap",
    "starttls": false,
    "tls_max_version": "tls12",
    "tls_min_version": "tls12",
    "url": "ldap://127.0.0.1"
  }
}
```

## Rotate root password

The `rotate-root` endpoint offers password rotation for the `binddn` entry used to manage LDAP.
This generated password will only be known to OpenBao and will not be retrievable once rotated.

| Method | Path                    |
| :----- | :---------------------- |
| `POST` | `/ldap/rotate-root` |

### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    http://127.0.0.1:8200/v1/ldap/rotate-root
```

## Static roles

The `static-role` endpoint configures OpenBao to manage the passwords of existing individual LDAP entries.

| Method   | Path                               |
| :------- | :--------------------------------- |
| `GET`    | `/ldap/static-role`            |
| `GET`    | `/ldap/static-role/:role_name` |
| `POST`   | `/ldap/static-role/:role_name` |
| `DELETE` | `/ldap/static-role/:role_name` |

### Parameters

- `username` `(string: <required>)` - The username of the existing LDAP entry to manage
  password rotation for. LDAP search for the username will be rooted at the [userdn](/api-docs/secret/ldap#userdn)
  configuration value. The attribute to use when searching for the user can be configured
  with the [userattr](/api-docs/secret/ldap#userattr) configuration value. This is useful
  when `dn` isn't used for login purposes (such as SSH). Cannot be modified after creation.<br />
  **Example:** `"bob"`
- `dn` `(string: <optional>)` - Distinguished name (DN) of the existing LDAP entry to manage
  password rotation for. If given, it will take precedence over `username` for the LDAP
  search performed during password rotation. Cannot be modified after creation.<br />
  **Example:** `cn=bob,ou=Users,dc=openbao,dc=com`
- `rotation_period` `(string: <required>)` - How often OpenBao should rotate the password of the user entry. Accepts
  [duration format strings](/docs/concepts/duration-format). The minimum rotation period is 5 seconds.<br />
  **Example:** `"3600", "5s", "1h"`

### Sample payload

```json
{
  "dn": "cn=openbao,ou=Users,dc=openbao,dc=com",
  "rotation_period": "24h",
  "username": "openbao"
}
```

### Sample POST request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/ldap/static-role/openbao
```

### Sample GET request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request GET \
    http://127.0.0.1:8200/v1/ldap/static-role/openbao
```

### Sample GET response

```json
{
  "data": {
    "dn": "uid=openbao,ou=Users,dc=openbao,dc=com",
    "last_vault_rotation": "2020-02-19T11:31:53.7812-05:00",
    "rotation_period": 86400,
    "username": "openbao"
  }
}
```

### Sample LIST response

```json
["openbao", "bob"]
```

## Static role passwords

The `static-cred` endpoint offers the credential information for a given static-role.

| Method | Path                               |
| :----- | :--------------------------------- |
| `GET`  | `/ldap/static-cred/:role_name` |

#### Sample get request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request GET \
    http://127.0.0.1:8200/v1/ldap/static-cred/openbao
```

#### Sample get response

```json
{
  "dn": "uid=openbao,ou=Users,dc=openbao,dc=com",
  "last_vault_rotation": "2020-02-19T11:31:53.7812-05:00",
  "password": "LTNfyn7pS7XEZIxEYQ2sEAWic02PEP7zSvIs0xMqIjaU0ORzLhKOKVmYLxL1Xkyv",
  "last_password": "?@09AZSen9TzUwK7ZhafS7B0GuWGraQjfWEna5SwnmF/tVaKFqjXhhGV/Z0v/pBJ",
  "rotation_period": 86400,
  "ttl": 86072,
  "username": "openbao"
}
```

## Manually rotate static role password

The `rotate-role` endpoint rotates the password of an existing static role.

| Method | Path                               |
| :----- | :--------------------------------- |
| `POST` | `/ldap/rotate-role/:role_name` |

### Sample request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    http://127.0.0.1:8200/v1/ldap/rotate-role/:role_name
```

## Dynamic roles

Create or update a dynamic role configuration. This provides instructions to OpenBao on how to create an
LDAP domain user account.

### Create/Delete dynamic role configuration

Creates, updates, or deletes a dynamic role.

| Method   | Path                        |
| :------- | :-------------------------- |
| `POST`   | `/ldap/role/:role_name` |
| `DELETE` | `/ldap/role/:role_name` |

The `POST` endpoint allows for partial updates of existing roles. If a role exists and a `POST` request is made
against it, only the keys specified in the request will be updated. To delete a value, specify the key with an
empty string as the value. Example: `openbao write ldap/role/myrole default_ttl=""`

#### Parameters

- `role_name` `(string, required)` - The name of the dynamic role.
- `creation_ldif` `(string, required)` - A templatized LDIF string used to create a user account. This may contain
  multiple LDIF entries. The `creation_ldif` can also be used to add the user account to an **_existing_** group.
  All LDIF entries are performed in order. If OpenBao encounters an error while executing the `creation_ldif` it will
  stop at the first error and not execute any remaining LDIF entries. If an error occurs and `rollback_ldif` is
  specified, the LDIF entries in `rollback_ldif` will be executed. See `rollback_ldif` for more details. This field
  may optionally be provided as a base64 encoded string.
- `deletion_ldif` `(string, required)` - A templatized LDIF string used to delete the user account once its TTL has
  expired. This may contain multiple LDIF entries. All LDIF entries are performed in order. If OpenBao encounters an
  error while executing an entry in the `deletion_ldif` it will attempt to continue executing any remaining entries.
  This field may optionally be provided as a base64 encoded string.
- `rollback_ldif` `(string, not required but recommended)` - A templatized LDIF string used to attempt to rollback
  any changes in the event that execution of the `creation_ldif` results in an error. This may contain multiple LDIF
  entries. All LDIF entries are performed in order. If OpenBao encounters an error while executing an entry in the
  `rollback_ldif` it will attempt to continue executing any remaining entries. This field may optionally be provided
  as a base64 encoded string.
- `username_template` `(string)` - A template used to generate a dynamic username. This will be used to fill in the
  `.Username` field within the `creation_ldif` string.

<details>
<summary><b>Default Username Template</b></summary>

```
v_{{.DisplayName}}_{{.RoleName}}_{{random 10}}_{{unix_time}}
```

<details>
<summary><b>Example Usernames:</b></summary>

| Example       |                                            |
| ------------- | ------------------------------------------ |
| `DisplayName` | `token`                                    |
| `RoleName`    | `myrolename`                               |
| Username      | `v_token_myrolename_uszt1n4cyh_1614294836` |

| Example       |                                                                      |
| ------------- | -------------------------------------------------------------------- |
| `DisplayName` | `amuchlonger_dispname`                                               |
| `RoleName`    | `role-name-with-dashes`                                              |
| Username      | `v_amuchlonger_dispname_role-name-with-dashes_s0t9xb0jsa_1614294836` |

</details>
</details>

- `default_ttl` `(string/int)` - Specifies the TTL for the leases associated with this role. Accepts
  [duration format strings](/docs/concepts/duration-format). Defaults to system/engine default TTL time.
- `max_ttl` `(string/int)` - Specifies the maximum TTL for the leases associated with this role. Accepts
  [duration format strings](/docs/concepts/duration-format). Defaults to system/mount default TTL time;
  this value is allowed to be less than the mount max TTL (or, if not set, the system max TTL),
  but it is not allowed to be longer.

The `creation_ldif`, `deletion_ldif`, `rollback_ldif`, and `username_template` fields are all templated fields. See
[Username Templating](/docs/concepts/username-templating) for details on how to use templating. Also see
[Templates](#templates) for specifics on what data is available for each template.

#### Sample payload

Sample LDIF files:

`creation.ldif`:

```
dn: cn={{.Username}},ou=users,dc=learn,dc=example
objectClass: person
objectClass: top
cn: learn
sn: {{.Password | utf16le | base64}}
memberOf: cn=dev,ou=groups,dc=learn,dc=example
userPassword: {{.Password}}
```

`deletion.ldif` & `rollback.ldif`:

```
dn: cn={{.Username}},ou=users,dc=learn,dc=example
changetype: delete
```

Full Payload:

```json
{
  "creation_ldif": "...",
  "deletion_ldif": "...",
  "rollback_ldif": "...",
  "username_template": "...",
  "default_ttl": "1h",
  "max_ttl": "24h"
}
```

:::info

Note: The LDIF statements may optionally be base64 encoded. If they are base64 encoded when creating/updating the
role configuration, the decoded version will be returned from the `GET` endpoint.

:::

#### Sample POST request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/ldap/role/dynamic-role
```

### Read dynamic role configuration

Retrieves a dynamic role's configuration.

| Method | Path                        |
| ------ | --------------------------- |
| `GET`  | `/ldap/role/:role_name` |

#### Response

`200 OK`

```json
{
  "creation_ldif": "...",
  "default_ttl": 1800,
  "deletion_ldif": "...",
  "max_ttl": 0,
  "rollback_ldif": "...",
  "username_template": "..."
}
```

### Templates

LDIF and username templates use the [Go template syntax](https://golang.org/pkg/text/template/) to construct the
LDIF/username that will be executed against the server. This is done because certain values (such as the username
and password within an LDIF statement) are not known at configuration time. Additionally, the template gives a
lot of flexibility to the operator to construct the LDIF and username.

Templated fields are delimited by `{{` and `}}`. To reference a field (such as the generated `Username`), a period is
placed in front of the field name. Example: `{{.Username}}`. Spaces can be included between `{{` and `}}`. For instance:
`{{.Username|lowercase}}` is the same as `{{ .Username | lowercase }}`.

If a field needs to be modified (such as SHA256 hashing, base64 encoding, etc.) the value can be sent to one of the
[built-in functions](#template-functions). This uses a "pipe" syntax: `{{.Username | base64}}`. Values may be "piped"
to multiple functions: `{{.Username | lowercase | base64}}`

#### LDIF template fields

The following parameters are available within the LDIF templates:

`.Username` - The name of the generated user (optionally from `username_template`).<br />
**Default pattern:** `v_<display name>_<role name>_<10 random chars>_<unix timestamp>`

`.Password` - The generated password (optionally from
[password policies](/docs/concepts/password-policies))

`.RoleName` - The name of the role that credentials are being generated for.

`.DisplayName` - The display name associated with the authentication token used to make the credentials request.

`.IssueTime` - The time that the lease was created. This time may be slightly earlier than the associated lease due to
where this value is calculated compared with where OpenBao calculates details of the lease.<br />
**Format:** 2006-01-02T15:04:05Z07:00 ([RFC3339](https://golang.org/pkg/time/#pkg-constants))

`.IssueTimeSeconds` - The [unix time](https://en.wikipedia.org/wiki/Unix_time) the lease was created. This time may
be slightly earlier than the associated lease due to where this value is calculated compared with where OpenBao
calculates details of the lease.<br />
**Format:** Integer indicating the number of seconds elapsed since January 1, 1970.

`.ExpirationTime` - The time that the lease is set to expire. This time may be slightly earlier than the associated
lease due to where this value is calculated compared with where OpenBao calculates details of the lease.<br />
**Format:** 2006-01-02T15:04:05Z07:00 ([RFC3339](https://golang.org/pkg/time/#pkg-constants))

`.ExpirationTimeSeconds` - The [unix time](https://en.wikipedia.org/wiki/Unix_time) the lease is set to expire. This
time may be slightly earlier than the associated lease due to where this value is calculated compared with where OpenBao
calculates details of the lease.<br />
**Format:** Integer indicating the number of seconds elapsed since January 1, 1970.

#### Username template fields

The following parameters are available within the username template:

**Important note:** If any of the following fields include dashes or underscores, they will not be removed/changed
unless explicitly done so within the username template. For instance:

If `RoleName` is `test-role` and the `username_template` is `v_{{.RoleName}}_{{unix_time}}`, the result of this template
may be: `v_test-role_1234567890`. Note the `-` (dash) in the `test-role`. If the LDAP system OpenBao is managing
restricts usernames/DNs to not allow for dashes (or other characters), the template must explicitly modify/remove those
characters. In this example, the template can be changed to `v_{{.RoleName | replace "-" "_"}}` to replace
the dashes with underscores. See [Template Functions](#template-functions) for more functions available.

`.RoleName` - The name of the role the credentials are being generated from.

`.DisplayName` - The display name associated with the user making the request against Value.

#### Template functions

Both the LDIF templates and the username template use the [Go template language](https://golang.org/pkg/text/template)
so all [functions](https://golang.org/pkg/text/template/#hdr-Functions) and capabilities from that language are
supported including functions such as `printf`.

In addition to the functions available through the template language, the following custom functions are also available:

`random` - Generates a random string from lowercase letters, uppercase letters, and numbers. Must include a
number indicating how many characters to generate.<br />
**Example:** `{{random 20}}` generates 20 random characters

`truncate` - truncates the previous value to the provided number of characters.<br />
**Example:** `{{.FieldName | truncate 10}}`

`truncate_sha256` - Truncates the previous value to the provided number of characters. The last 8 characters of the
truncated value will be the first 8 characters of the SHA256 hash of the truncated characters.

This can aid in identifying values (such as the role & display names) if they need to be truncated to a particular
length, particularly if the value has common prefixes. An example of this is having many roles with a common prefix in
the name of the role, but the role name is truncated such that only the prefix is shown. This function will keep the
non-prefix part of the role name in the username which will aid in identification while also keeping uniqueness.

**Example:**<br />
`v_{{.RoleName | truncate_sha256 15}}_{{unix_time}}`. <br />
If two roles exist for this template, `myreallylongprefix-foobar` and `myreallylongprefix-bazqux`, the username for the first role
would be `v_myrealle6da86ec_1234567890` and the username for the second role would be `v_myrealld0420a55_1234567890`.

`uppercase` - Uppercases the provided value.<br />
**Example:** `{{.FieldName | uppercase}}`

`lowercase` - Lowercases the provided value.<br />
**Example:** `{{.FieldName | lowercase}}`

`replace` - Find/replace on the provided value.<br />
**Example:** `{{.FieldName | replace "-" "_"}}`

`sha256` - SHA256 hashes the provided value.<br />
**Example:** `{{.FieldName | sha256}}`

`base64` - Base64 encodes the provided value.<br />
**Example:** `{{.FieldName | base64}}`

`unix_time` - The current unix timestamp (number of seconds since Jan 1 1970).<br />
**Example:** `{{unix_time}}`

`unix_time_millis` - The current unix timestamp in milliseconds.<br />
**Example:** `{{unix_time_millis}}`

`timestamp` - The current time. Must provide a formatting string based on Go’s time package.<br />
**Example:** `{{timestamp "2006-01-02T15:04:05Z"}}`

`uuid` - Generates a random UUID.<br />
**Example:** `{{uuid}}`

##### LDIF template functions

Additionally, the LDIF templates include an additional function to facilitate Active Directory password handling.
The username template cannot use this function.

`utf16le` - Encodes the provided value into UTF16-LE.<br />
**Example:** `{{.FieldName | utf16le}}`

## Dynamic role passwords

The `creds` endpoint offers the credential information for a given dynamic role.

| Method | Path                               |
| :----- | :--------------------------------- |
| `GET`  | `/ldap/creds/:role_name` |

#### Sample get request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request GET \
    http://127.0.0.1:8200/v1/ldap/creds/dynamic-role
```

#### Sample get response

```json
{
  "distinguished_names": [
    "cn=v_token-dispname_testrole_jmZMnjS42a_1680580467,ou=users,dc=openbao,dc=com"
  ],
  "password": "OWexB3OzYYLFiotWxUS2EheGpriwR20fa2yA7JGTsnBREcxyqpwf73htofMihxcC",
  "username": "v_token-dispname_testrole_jmZMnjS42a_1680580467"
}
```

## Library set management

The `library` endpoint configures the sets of service accounts that OpenBao will offer for check-out.

| Method   | Path                    |
| :------- | :---------------------- |
| `LIST`   | `/ldap/library`           |
| `POST`   | `/ldap/library/:set_name` |
| `GET`    | `/ldap/library/:set_name` |
| `DELETE` | `/ldap/library/:set_name` |

When adding a service account to the library, OpenBao verifies it already exists in the LDAP directory.

### Parameters

- `name` `(string: "", required)` - The name of the set of service accounts.
- `service_account_names` `(string: "", or list: [] required)` - The names of all the service accounts that can be
  checked out from this set. These service accounts must only be used by OpenBao, and may only be in one set. These
  service accounts must already exist in the LDAP directory.
- `ttl` `(duration: "24h", optional)` - The maximum amount of time a single check-out lasts before OpenBao
  automatically checks it back in. Defaults to 24 hours. Setting it to zero reflects an unlimited lending period.
  Uses [duration format strings](/docs/concepts/duration-format).
- `max_ttl` `(duration: "24h", optional)` - The maximum amount of time a check-out last with renewal before OpenBao
  automatically checks it back in. Defaults to 24 hours. Setting it to zero reflects an unlimited lending period.
  Uses [duration format strings](/docs/concepts/duration-format).
- `disable_check_in_enforcement` `(bool: false, optional)` - Disable enforcing that service accounts must be
  checked in by the entity or client token that checked them out. Defaults to false.

### Sample POST request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/ldap/library/accounting-team
```

### Sample POST payload

```json
{
  "service_account_names": ["fizz@example.com", "buzz@example.com"],
  "ttl": "10h",
  "max_ttl": "20h",
  "disable_check_in_enforcement": false
}
```

### Sample GET response

```json
{
  "service_account_names": ["fizz@example.com", "buzz@example.com"],
  "ttl": "10h",
  "max_ttl": "20h",
  "disable_check_in_enforcement": false
}
```

### Sample LIST response

Performing a `LIST` on the `/ldap/library` endpoint will list the names of all the sets of service accounts OpenBao contains.

```json
["accounting-team"]
```

## Library set status check

This endpoint provides the check-out status of service accounts in a library set.

| Method | Path                           |
| :----- | :----------------------------- |
| `GET`  | `/ldap/library/:set_name/status` |

### Sample GET request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request GET \
    http://127.0.0.1:8200/v1/ldap/library/accounting-team/status
```

### Sample GET response

```json
{
  "request_id": "9e44c8b5-d142-5867-2a11-49f3ba71215a",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "buzz@example.com": {
      "available": true
    },
    "fizz@example.com": {
      "available": false,
      "borrower_client_token": "4c653e473bf7e27c6759fccc3def20c44d776279",
      "borrower_entity_id": "631256b1-8523-9838-5501-d0a1e2cdad9c"
    }
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}
```

## Check-Out management

This endpoint provides service account check out for a library set.

| Method | Path                              |
| :----- | :-------------------------------- |
| `POST` | `/ldap/library/:set_name/check-out` |

Returns a `200` if a credential is available, and a `400` if no credential is available.

### Parameters

- `name` `(string: "", required)` - The name of the set of service accounts.
- `ttl` `(duration: "", optional)` - The maximum amount of time a check-out lasts before OpenBao
  automatically checks it back in. Setting it to zero reflects an unlimited lending period.
  Defaults to the set's `ttl`. If the requested `ttl` is higher than the set's, the set's will be used.
  Uses [duration format strings](/docs/concepts/duration-format).

### Sample POST request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/ldap/library/accounting-team/check-out
```

### Sample POST payload

```json
{
  "ttl": "1h"
}
```

### Sample POST response

```json
{
  "request_id": "364a17d4-e5ab-998b-ceee-b49929229e0c",
  "lease_id": "ad/library/accounting-team/check-out/aoBsaBEI4PK96VnukubvYDlZ",
  "renewable": true,
  "lease_duration": 36000,
  "data": {
    "password": "?@09QW0KZ8DSBu3deIu7XLY1NZqzwhozmMAZ6v0IcZJGOjs5GvpVMvOeW7/duls2",
    "service_account_name": "fizz@example.com"
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}
```

## Check-In management

By default, check-in must be called by the same entity or client token used for check-out.
To disable this behavior, use the `disable_check_in_enforcement` toggle on the library set. Or, use
the `ad/library/manage/:set_name/check-in` behavior to force check-in of the account. Access to the
"manage" endpoint should only be granted to highly privileged OpenBao users, like OpenBao operators.

If a caller attempts to check in a service account they're not authorized to check in, they will
receive an error response. If they attempt to check in a service account they _are_ authorized to
check in, but it's _already_ checked in, they will receive a successful response but the account
will not be included in the `check_ins` listed. `check_ins` shows which service accounts were checked
in _by this particular call_.

| Method | Path                                    |
| :----- | :-------------------------------------- |
| `POST` | `/ldap/library/:set_name/check-in`        |
| `POST` | `/ldap/library/manage/:set_name/check-in` |

### Parameters

- `name` `(string: "", required)` - The name of the set of service accounts.
- `service_account_names` `(string: "", or list: [] optional)` - The names of all the service accounts to be
  checked in. May be omitted if only one is checked out.

### Sample POST request

```shell-session
$ curl \
    --header "X-Vault-Token: ..." \
    --request POST \
    --data @payload.json \
    http://127.0.0.1:8200/v1/ldap/library/accounting-team/check-in
```

### Sample POST payload

```json
{
  "service_account_names": ["fizz@example.com"]
}
```

### Sample POST response

```json
{
  "request_id": "db45c714-3f68-b748-95bc-8f7467637a52",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "check_ins": ["fizz@example.com"]
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}
```
